Skip to content

fix(payload): actionable error from cloudsync_payload_chunks when uninitialized#54

Merged
andinux merged 2 commits into
mainfrom
fix/payload-chunks-uninitialized-error
Jul 13, 2026
Merged

fix(payload): actionable error from cloudsync_payload_chunks when uninitialized#54
andinux merged 2 commits into
mainfrom
fix/payload-chunks-uninitialized-error

Conversation

@andinux

@andinux andinux commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Problem

When the /check endpoint queries cloudsync_payload_chunks on a database that is initialized for cloudsync locally but not configured on the cloud node, the server receives a misleading error:

Database query failed: SQL logic error

while cloudsync_payload_apply in the same scenario already returns the actionable message:

cloudsync is not initialized: call SELECT cloudsync_init('<table_name>') to enable sync on a table before calling cloudsync_payload_apply().

Root cause

cloudsync_payload_chunks is a virtual table whose xFilter runs internal statements over the eponymous cloudsync_changes vtab. On an unconfigured database those statements prepare fine but fail at step time, and the error code propagated out of xFilter without ever setting the outer vtab's zErrMsg, so SQLite surfaced the generic "SQL logic error". The watermark MAX(db_version) query even discarded its step error entirely, silently scanning an empty window.

Fix

  • payload_chunks_filter now starts with the same cloudsync_context_is_initialized guard used by cloudsync_payload_apply and raises: "cloudsync is not initialized: call SELECT cloudsync_init('<table_name>') to enable sync on a table before querying cloudsync_payload_chunks."
  • payload_chunks_step_source copies the inner statement's error message onto the vtab's zErrMsg, so any other inner error (e.g. "cloudsync has no tables configured") reaches the caller instead of being masked.
  • A watermark-query step failure is propagated as an error instead of being ignored.

No PostgreSQL changes: the PG SRF errors through ereport/SPI with its own messages, and the extension version stays at 1.1 (patch bump only), so no migration script is needed.

Tests

  • New unit test Payload Chunks Uninitialized: runs the /check-style query on a database without cloudsync_init and asserts the actionable message. All 148 SQLite unit tests pass; PostgreSQL full suite passes with 0 failures.
  • The e2e Failure Path Test now asserts the forwarded "cloudsync is not initialized" message on all three surfaces (send lastFailure JSON, the non-retryable SQL error raised by receive_changes, and the sync JSON) instead of only checking that a lastFailure object exists. Note: this test stays red against server nodes still running the 1.1.0 extension (they forward the old "SQL logic error" text) and goes green once the node runs 1.1.1.
  • Verified manually: a fresh connection to an already-configured database is not falsely rejected (extension load-time init prepares the probe statement), and the exact reported /check query on an uninitialized db now returns the actionable message.

An independent review pass approved the change; noted follow-up (not in scope): on PostgreSQL, cloudsync_payload_chunks on an unconfigured node silently returns zero chunks rather than erroring — parity there is a separate product decision.

Versioning

  • CLOUDSYNC_VERSION bumped to 1.1.1 (bug shipped in released 1.1.0)
  • CHANGELOG entry added under ## [1.1.1] - 2026-07-10

🤖 Generated with Claude Code

andinux and others added 2 commits July 10, 2026 16:47
…nitialized

Querying the cloudsync_payload_chunks vtab on a database where cloudsync
was never initialized surfaced a bare "SQL logic error": the internal
statements over cloudsync_changes failed at step time and the error code
propagated out of xFilter without ever setting the outer vtab's zErrMsg.
The /check endpoint hit this on nodes not configured for cloudsync.

Guard xFilter with the same is-initialized check (and message) used by
cloudsync_payload_apply, propagate inner-statement messages onto the
vtab, and stop ignoring watermark MAX() step failures.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…re path

The Failure Path Test only checked that a lastFailure object existed. Now
that cloudsync_payload_chunks propagates its error, the server forwards
"cloudsync is not initialized" for the check job too (previously a bare
"SQL logic error"), so assert the message on all three surfaces: the
send lastFailure JSON, the non-retryable SQL error raised by
receive_changes, and the sync JSON. Goes green once the node runs 1.1.1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@andinux andinux merged commit a8253cb into main Jul 13, 2026
50 of 61 checks passed
@andinux andinux deleted the fix/payload-chunks-uninitialized-error branch July 13, 2026 07:56
andinux added a commit that referenced this pull request Jul 14, 2026
…bles are missing (#55)

Querying cloudsync_changes (directly or via cloudsync_payload_blob_checked)
on a database whose cloudsync_table_settings rows survived while every
*_cloudsync meta table was lost — e.g. a dump/restore that skipped them —
returned SQLITE_NOMEM: the NULL from vtab_build_changes_sql fell through
the config-exists guard added in #54. SQLite Cloud reported it on the
/check path as "Not enough memory to execute query", pointing operators
at memory instead of the real state.

- xFilter now distinguishes this state (settings rows present, zero
  %_cloudsync tables in sqlite_master) and raises "cloudsync settings
  reference tables whose sync metadata is missing" with the re-init
  remediation; genuine OOM still returns SQLITE_NOMEM
- unit test: Changes Vtab Missing Meta Tables (red before, green after)
- bump CLOUDSYNC_VERSION to 1.1.2 and add the CHANGELOG entry (SQLite
  vtab only, no PG changes, extension version stays 1.1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant